package com.dtguai.admin.web.sys.controller.menu;


import com.dtguai.admin.base.action.BaseAction;
import com.dtguai.admin.common.annotation.SysLog;
import com.dtguai.admin.common.error.ErrorCode;
import com.dtguai.admin.common.exception.DefinedException;
import com.dtguai.admin.common.validator.BaseAssert;
import com.dtguai.admin.common.validator.ValidatorUtils;
import com.dtguai.admin.common.validator.group.AddGroup;
import com.dtguai.admin.common.validator.group.UpdateGroup;
import com.dtguai.admin.protocol.response.ApiResponse;
import com.dtguai.admin.util.constant.Constant;
import com.dtguai.admin.web.sys.form.menu.MenuForm;
import com.dtguai.admin.web.sys.model.menu.MenuPermissions;
import com.dtguai.admin.web.sys.model.menu.SysDefMenu;
import com.dtguai.admin.web.sys.service.ShiroService;
import com.dtguai.admin.web.sys.service.SysDefMenuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponses;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;

/**
 * SysDefMenu表相关操作
 *
 * @author guo
 * @date 2019年10月30日17:31:25
 */
@RestController
@RequestMapping("/web/sys/controller/menu")
@Api(value = "web-菜单管理接口", tags = {"web-菜单管理接口"})
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class SysDefMenuApi extends BaseAction {

    private SysDefMenuService sysDefMenuService;

    private ShiroService shiroService;

    private static final int MAX_ID = 32;

    /**
     * 导航菜单
     */
    @ApiOperation(value = "获取左边菜单和权限", notes = "获取左边菜单和权限")
    @GetMapping(value = "/getMenu", produces = "application/json;charset=UTF-8")
    public ResponseEntity<ApiResponse<MenuPermissions>> getMenu() {
        //获取左侧菜单
        List<SysDefMenu> menuList = sysDefMenuService.getAdminMenuList();
        //获取权限列表
        Set<String> permissions = shiroService.getUserPermissions(getAdminId());

        return ResponseEntity.ok(new ApiResponse<>(new MenuPermissions(menuList, permissions)));
    }


    /**
     * 所有菜单列表
     */
    @ApiOperation(value = "所有菜单列表", notes = "所有菜单列表")
    @GetMapping(value = "/list", produces = "application/json;charset=UTF-8")
    @RequiresPermissions("sys:menu:list")
    public ResponseEntity<ApiResponse<List<SysDefMenu>>> list() {

        List<SysDefMenu> menuList = sysDefMenuService.getAdminMenuList(new SysDefMenu());
        menuList.forEach(x -> {
            SysDefMenu parentMenuEntity = sysDefMenuService.selectByKey(x.getParentId());
            if (parentMenuEntity != null) {
                x.setParentName(parentMenuEntity.getName());
            }
        });

        return ResponseEntity.ok(new ApiResponse<>(menuList));
    }

    /**
     * select
     * 选择菜单(添加、修改菜单)
     */
    @ApiOperation(value = "选择菜单(添加、修改菜单)", notes = "选择菜单(添加、修改菜单)")
    @GetMapping(value = "/select", produces = "application/json;charset=UTF-8")
    @RequiresPermissions("sys:menu:select")
    public ResponseEntity<ApiResponse<List<SysDefMenu>>> select() {
        //查询列表数据
        List<SysDefMenu> menuList = sysDefMenuService.queryNotButtonList();

        //添加顶级菜单
        SysDefMenu root = new SysDefMenu();
        root.setId(0);
        root.setName("一级菜单");
        root.setParentId(-1);
        root.setOpen(true);
        menuList.add(root);

        return ResponseEntity.ok(new ApiResponse<>(menuList));
    }

    /**
     * 菜单信息
     */
    @ApiOperation(value = "菜单信息", notes = "菜单信息")
    @GetMapping(value = "/info", produces = "application/json;charset=UTF-8")
    @RequiresPermissions("sys:menu:info")
    public ResponseEntity<ApiResponse<SysDefMenu>> info(Integer id) {
        SysDefMenu menu = sysDefMenuService.selectByKey(id);
        return ResponseEntity.ok(new ApiResponse<SysDefMenu>(menu));
    }

    /**
     * 保存
     */
    @SysLog("保存菜单")
    @ApiOperation(value = "保存菜单", notes = "保存菜单")
    @PostMapping(value = "/save", produces = "application/json;charset=UTF-8")
    @RequiresPermissions("sys:menu:save")
    public ResponseEntity<ApiResponse> save(@RequestBody MenuForm menu) {
        //数据校验
        verifyForm(menu, AddGroup.class);
        sysDefMenuService.insertSelective(new ModelMapper().map(menu, SysDefMenu.class));
        return ResponseEntity.ok(new ApiResponse());
    }

    /**
     * 修改
     */
    @SysLog("修改菜单")
    @ApiOperation(value = "修改菜单", notes = "修改菜单")
    @PostMapping(value = "/update", produces = "application/json;charset=UTF-8")
    @RequiresPermissions("sys:menu:update")
    public ResponseEntity<ApiResponse> update(@RequestBody MenuForm menu) {
        //数据校验
        verifyForm(menu, UpdateGroup.class);
        sysDefMenuService.updateNotNull(new ModelMapper().map(menu, SysDefMenu.class));
        return ResponseEntity.ok(new ApiResponse());
    }


    /**
     * 删除
     */
    @SysLog("删除菜单")
    @ApiOperation(value = "删除菜单", notes = "删除菜单")
    @DeleteMapping(value = "/delete", produces = "application/json;charset=UTF-8")
    @RequiresPermissions("sys:menu:delete")
    @ApiResponses({
            @io.swagger.annotations.ApiResponse(code = 1022, message = "id不能为空")
    })
    @ApiImplicitParam(name = "id", value = "主键id", required = true, example = "")
    public ResponseEntity<ApiResponse> delete(@RequestBody Integer id) {
        BaseAssert.isNull(id, ErrorCode.ID_NOT_NULL);
        if (id <= MAX_ID) {
            throw new DefinedException(ErrorCode.NOT_SYS_MENU_DELETE);
        }
        //判断是否有子菜单或按钮
        SysDefMenu menu = new SysDefMenu();
        menu.setParentId(id);
        List<SysDefMenu> menuList = sysDefMenuService.selectByPage(menu, false, SysDefMenu.class);
        if (!menuList.isEmpty()) {
            throw new DefinedException(ErrorCode.NOT_SYS_MENU_DELETE_SUBMENU);
        }
        sysDefMenuService.delete(id);
        return ResponseEntity.ok(new ApiResponse());
    }

    /**
     * 验证参数是否正确
     */
    private void verifyForm(MenuForm menu, Class<?>... groups) {

        // 表单校验
        ValidatorUtils.validateEntity(menu, groups);

        //菜单
        if (menu.getType() == Constant.MenuType.MENU.getValue() && StringUtils.isBlank(menu.getUrl())) {
            throw new DefinedException("菜单URL不能为空");
        }

        //上级菜单类型
        int parentType = Constant.MenuType.CATALOG.getValue();
        if (menu.getParentId() != 0) {
            SysDefMenu parentMenu = sysDefMenuService.selectByKey(menu.getParentId());
            parentType = parentMenu.getType();
        }

        //目录、菜单
        if (menu.getType() == Constant.MenuType.CATALOG.getValue() ||
                menu.getType() == Constant.MenuType.MENU.getValue()) {
            if (parentType != Constant.MenuType.CATALOG.getValue()) {
                throw new DefinedException("上级菜单只能为目录类型");
            }
            return;
        }

        //按钮
        if (menu.getType() == Constant.MenuType.BUTTON.getValue() && parentType != Constant.MenuType.MENU.getValue()) {
            throw new DefinedException("上级菜单只能为菜单类型");
        }
    }
}